# -!-coding:utf-8-!-
# @Time: 2022/3/6
# @Dev: TJ

import gc
import time
import random
from pathlib import Path
from loguru import logger
from lxml import etree
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from src.sub_xpath.sub_xpath import xpath_string
from src.sub_faker.sub_faker_ua import SubFakerUA

fake = SubFakerUA()


class ProxyChannel:
    """ 代理 """
    CLOSE = None
    TX_CN7009 = 'http://10.0.3.43:7009'
    TX_CN5999 = 'socks5://10.0.3.43:5999'

    @staticmethod
    def random_proxy() -> str:
        return f'http://10.0.3.43:{random.randint(8001, 8016)}'


class SubFirefox(Firefox, ProxyChannel):
    def __init__(
            self,
            proxy=ProxyChannel.CLOSE,
            img_enabled=False,
            verify_enabled=False
    ):
        super().__init__(
            options=self.options(
                proxy=proxy,
                img_enabled=img_enabled,
                verify_enabled=verify_enabled)
        )

        # self.maximize_window()  # 窗口最大化
        self.set_page_load_timeout(31)  # 页面加载时间

    @staticmethod
    def options(proxy, img_enabled, verify_enabled):
        """ 浏览器初始化 """
        options = FirefoxOptions()
        options.headless = True  # 无界模式
        # options.add_argument('--headless')      # 无界模式
        options.add_argument('--no-sandbox')    # 取消沙盒模式
        options.add_argument('--disable-gpu')   # 谷歌文档提到需要加上这个属性来规避bug
        options.add_argument('--incognito')     # 无痕模式
        options.set_preference('general.useragent.override', fake.firefox())  # 伪装 UA

        if verify_enabled is False:
            options.add_argument('--ignore-certificate-errors')  # 关闭证书验证

        if img_enabled is False:
            options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片

        # 设置代理
        if proxy:
            proxy = str(proxy).replace('http://', '').replace('socks5://', '')
            proxy_url, proxy_port = str(proxy).split(':')
            options.set_preference('network.proxy.type', 1)
            options.set_preference('network.proxy.http', proxy_url)
            options.set_preference('network.proxy.http_port', int(proxy_port))
            options.set_preference('network.proxy.ssl', proxy_url)
            options.set_preference('network.proxy.ssl_port', int(proxy_port))

        print(options.preferences)
        return options

    def get(self, url) -> bool:
        try:
            for _ in range(3):
                super().get(url)

                if 'HTTP ERROR 503' in self.page_source:
                    logger.warning('HTTP ERROR 503')
                    time.sleep(1)
                    continue

                if self.title.find('江苏反诈公益宣传') >= 0:
                    logger.warning('江苏反诈公益宣传')
                    time.sleep(1)
                    continue

                return True

        except Exception as exception:
            logger.error(f'Exception: {exception} | Why?')

        return False

    def wait_element(self, element_type: str, element_name: str):
        """ 等待元素可见 """
        try:
            wait = WebDriverWait(self, 30)  # 设置等待时间
            wait.until(EC.visibility_of_element_located((
                element_type, element_name)))  # 当出现该条件，终止等待
            return True

        except Exception as exception:
            logger.error(exception)

        return False

    def screenshot_as_file(self, file_name=None, path='./screenshot_png') -> str:
        """ 网页截图保存本地 """
        if not file_name:
            url: str = self.current_url
            file_name = url.split('/')[-1]

        if not file_name:
            file_name = '%06d' % random.randint(0, 999999)

        file_name = '.'.join([file_name, 'png'])

        path = Path(path, file_name)
        path.parent.mkdir(parents=True, exist_ok=True)

        self.get_screenshot_as_file(str(path.absolute()))
        return str(path.absolute())

    def quit(self):
        """ 退出 driver """
        logger.info(f'quit: {self}')
        super().close()
        super().quit()

    def stop_client(self):
        """ 停止客户端 """
        logger.info(f'stop_client: {self}')
        super().stop_client()
        gc.collect()  # 回收资源


if __name__ == '__main__':
    while True:
        try:
            driver = SubFirefox(proxy=ProxyChannel.TX_CN7009)
            driver.get('http://myip.ipip.net/')
            html = etree.HTML(driver.page_source)
            print(xpath_string(html, '.', scrapy=False))
            print('截图路径:', driver.screenshot_as_file())
            time.sleep(3)
            driver.quit()
            del driver

        except Exception as e:
            print(e)
            break
